package com.danieldura.highrise.requests
{
	import com.danieldura.highrise.HighriseCredentials;
	import com.danieldura.highrise.data.HighriseData;
	import com.danieldura.highrise.events.HighriseRequestEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	
	import mx.rpc.AsyncToken;
	import mx.utils.Base64Encoder;
	
	[Event(name="result",type="com.danieldura.highrise.events.HighriseRequestEvent")]
	[Event(name="fault",type="com.danieldura.highrise.events.HighriseRequestEvent")]
	
	public class HighriseRequest extends EventDispatcher
	{
		public static const FORMAT_XML:String = ".xml";
		public static const FORMAT_VCARD:String = ".vcf";
		public static const FORMAT_CSV:String = ".csv";
		public static const FORMAT_ATOM:String = ".atom";
		
		protected var location:String;
		protected var requestMethod:String;
		protected var requestData:String;
		protected var format:String = FORMAT_XML;
		protected var currentLoader:URLLoader;
		protected var currentToken:HighriseRequestToken;
		protected var credentials:HighriseCredentials;
		protected var dataMap:HighriseRequestDataMap;
		
		public function HighriseRequest( credentials:HighriseCredentials, dataMap:HighriseRequestDataMap ):void
		{
			this.credentials = credentials;
			this.dataMap = dataMap;
		}
		
		protected function send():HighriseRequestToken
		{
         	var encoder:Base64Encoder = new Base64Encoder();
         	
         	if( credentials.token )
            	encoder.encode( credentials.token + ":X" );
			else
				encoder.encode( credentials.username + ":" +  credentials.password );
				                
            var authHeader:URLRequestHeader = new URLRequestHeader( "AUTHORIZATION", "Basic " + encoder.drain() );
            
			var request:URLRequest = new URLRequest( credentials.domain + location );
			request.method = requestMethod;
			request.data = requestData;
			request.contentType = "application/xml";
            request.requestHeaders = [ authHeader ];
                
			currentLoader = new URLLoader( request );
			currentLoader.addEventListener( Event.COMPLETE, handle_loaderComplete );
			currentLoader.addEventListener( SecurityErrorEvent.SECURITY_ERROR, handle_loaderError );
			//currentLoader.addEventListener( HTTPStatusEvent.HTTP_STATUS, handle_loaderError );
			
			currentToken = new HighriseRequestToken();
			return currentToken;
		}
		
		private function handle_loaderComplete( event:Event ):void
		{
			var responseData:* = parseResponse( URLLoader( event.target ).data );
			dispatchEvent( new HighriseRequestEvent( HighriseRequestEvent.RESULT, responseData, currentToken ) );
		}
		
		private function handle_loaderError( event:Event ):void
		{
			dispatchEvent( new HighriseRequestEvent( HighriseRequestEvent.FAULT, null, currentToken ) );
		}
		
		protected function parseResponse( data:* ):*
		{
			var item:HighriseData;
			
			if( format == FORMAT_XML )
			{
				var xmlData:XML = new XML( data );
				if( xmlData.localName() == dataMap.plural )
				{
					var items:Array = new Array();
					for each( var itemData:XML in xmlData[dataMap.singular] )
					{
						item = new dataMap.dataClass();
						item.parse( itemData );
						items.push( item );
					}
					return items;
				}
				else if( xmlData.localName() == dataMap.singular )
				{
					item = new dataMap.dataClass();
					item.parse( xmlData );
					return item;
				}
			}
			
			return null;
		}
		
		// encodes a date into the string format yyyymmddhhmmss
		protected function encodeDate( dateTime:Date ):String
		{
			var dateStr:String = "";
			dateStr += dateTime.getUTCFullYear();
			dateStr += dateTime.getUTCMonth() + 1;
			dateStr += dateTime.getUTCDate();
			dateStr += dateTime.getUTCHours();
			dateStr += dateTime.getUTCMinutes();
			dateStr += dateTime.getUTCSeconds();
			return dateStr;
		}
		
	}
}